<?php
declare (strict_types = 1);

namespace app\admin\service;

// use think\Image; // 使用独立Image扩展
use think\Request;

/**
 * 文件上传服务类
 */
class UploadService
{
    // 默认配置
    private static $defaultConfig = [
        'disk' => 'public',  // 默认使用public磁盘
        'path' => 'uploads', // 默认上传路径
        'maxSize' => 2 * 1024 * 1024, // 默认最大2MB
        'allowExt' => ['jpg', 'jpeg', 'png', 'gif', 'webp'], // 默认允许的扩展名
        'allowMime' => ['image/jpeg', 'image/png', 'image/gif', 'image/webp'], // 允许的MIME类型
    ];

    /**
     * 上传头像
     */
    public static function uploadAvatar($file, int $userId = 0): array
    {
        $config = array_merge(self::$defaultConfig, [
            'path' => 'uploads/avatars/' . date('Ymd'),
            'maxSize' => 1 * 1024 * 1024, // 头像限制1MB
            'allowExt' => ['jpg', 'jpeg', 'png', 'webp'],
            'allowMime' => ['image/jpeg', 'image/png', 'image/webp'],
        ]);

        $result = self::upload($file, $config);
        
        if ($result['code'] === 0) {
            // 生成缩略图
            $result['data']['thumb'] = self::generateThumbnail($result['data']['path'], 120, 120);
        }

        return $result;
    }

    /**
     * 上传普通图片
     */
    public static function uploadImage($file, string $path = 'images'): array
    {
        $config = array_merge(self::$defaultConfig, [
            'path' => $path . '/' . date('Y/m'),
            'maxSize' => 5 * 1024 * 1024, // 图片限制5MB
        ]);

        return self::upload($file, $config);
    }

    /**
     * 上传文档
     */
    public static function uploadDocument($file, string $path = 'documents'): array
    {
        $config = array_merge(self::$defaultConfig, [
            'path' => $path . '/' . date('Y/m'),
            'maxSize' => 10 * 1024 * 1024, // 文档限制10MB
            'allowExt' => ['pdf', 'doc', 'docx', 'xls', 'xlsx', 'ppt', 'pptx', 'txt'],
            'allowMime' => [
                'application/pdf',
                'application/msword',
                'application/vnd.openxmlformats-officedocument.wordprocessingml.document',
                'application/vnd.ms-excel',
                'application/vnd.openxmlformats-officedocument.spreadsheetml.sheet',
                'application/vnd.ms-powerpoint',
                'application/vnd.openxmlformats-officedocument.presentationml.presentation',
                'text/plain'
            ],
        ]);

        return self::upload($file, $config);
    }

    /**
     * 上传素材
     */
    public static function uploadMaterial($file, string $type = 'image'): array
    {
        $config = [];
        
        // 根据素材类型设置不同的配置
        switch ($type) {
            case 'image':
                $config = [
                    'path' => 'material/images/' . date('Y/m'),
                    'maxSize' => 5 * 1024 * 1024, // 图片限制5MB
                    'allowExt' => ['jpg', 'jpeg', 'png', 'gif', 'webp'],
                    'allowMime' => ['image/jpeg', 'image/png', 'image/gif', 'image/webp'],
                ];
                break;
                
            case 'video':
                $config = [
                    'path' => 'material/videos/' . date('Y/m'),
                    'maxSize' => 100 * 1024 * 1024, // 视频限制100MB
                    'allowExt' => ['mp4', 'avi', 'mov', 'wmv', 'flv', 'webm'],
                    'allowMime' => [
                        'video/mp4',
                        'video/avi',
                        'video/quicktime',
                        'video/x-ms-wmv',
                        'video/x-flv',
                        'video/webm'
                    ],
                ];
                break;
                
            case 'audio':
                $config = [
                    'path' => 'material/audios/' . date('Y/m'),
                    'maxSize' => 20 * 1024 * 1024, // 音频限制20MB
                    'allowExt' => ['mp3', 'wav', 'ogg', 'flac', 'm4a'],
                    'allowMime' => [
                        'audio/mpeg',
                        'audio/wav',
                        'audio/ogg',
                        'audio/flac',
                        'audio/mp4'
                    ],
                ];
                break;
                
            case 'document':
                $config = [
                    'path' => 'material/documents/' . date('Y/m'),
                    'maxSize' => 20 * 1024 * 1024, // 文档限制20MB
                    'allowExt' => ['pdf', 'doc', 'docx', 'xls', 'xlsx', 'ppt', 'pptx', 'txt'],
                    'allowMime' => [
                        'application/pdf',
                        'application/msword',
                        'application/vnd.openxmlformats-officedocument.wordprocessingml.document',
                        'application/vnd.ms-excel',
                        'application/vnd.openxmlformats-officedocument.spreadsheetml.sheet',
                        'application/vnd.ms-powerpoint',
                        'application/vnd.openxmlformats-officedocument.presentationml.presentation',
                        'text/plain'
                    ],
                ];
                break;
                
            default:
                $config = [
                    'path' => 'material/others/' . date('Y/m'),
                    'maxSize' => 20 * 1024 * 1024, // 其他限制20MB
                    'allowExt' => ['zip', 'rar', '7z', 'tar', 'gz', 'bz2', 'pdf', 'txt', 'doc', 'docx', 'xls', 'xlsx', 'ppt', 'pptx'],
                    'allowMime' => [
                        'application/zip',
                        'application/x-rar-compressed',
                        'application/x-7z-compressed',
                        'application/x-tar',
                        'application/gzip',
                        'application/x-bzip2',
                        'application/pdf',
                        'text/plain',
                        'application/msword',
                        'application/vnd.openxmlformats-officedocument.wordprocessingml.document',
                        'application/vnd.ms-excel',
                        'application/vnd.openxmlformats-officedocument.spreadsheetml.sheet',
                        'application/vnd.ms-powerpoint',
                        'application/vnd.openxmlformats-officedocument.presentationml.presentation'
                    ],
                ];
        }
        
        // 使用通用上传方法
        return self::upload($file, $config);
    }

    /**
     * 通用文件上传方法
     */
    public static function upload($file, array $config = []): array
    {
        try {
            // 合并配置
            $config = array_merge(self::$defaultConfig, $config);

            // 验证文件
            $validateResult = self::validateFile($file, $config);
            if ($validateResult['code'] !== 0) {
                return $validateResult;
            }

            // 构建上传目录
            // ROOT_PATH 是 source/ 目录，web 目录在上一级
            $webPath = dirname(ROOT_PATH) . DS . 'web' . DS;
            $uploadPath = $webPath . $config['path'];
            
            // 确保目录存在
            if (!is_dir($uploadPath)) {
                mkdir($uploadPath, 0755, true);
            }

            // 使用TP5.0的move方法上传文件
            $info = $file->validate([
                'size' => $config['maxSize'],
                'ext' => implode(',', $config['allowExt'])
            ])->move($uploadPath);

            if (!$info) {
                return [
                    'code' => 1,
                    'msg' => '文件上传失败：' . $file->getError(),
                    'data' => null
                ];
            }

            // 获取文件信息
            $fileInfo = self::getFileInfo($file, $info, $config);

            return [
                'code' => 0,
                'msg' => '上传成功',
                'data' => $fileInfo
            ];

        } catch (\Exception $e) {
            return [
                'code' => 1,
                'msg' => '上传异常：' . $e->getMessage(),
                'data' => null
            ];
        }
    }

    /**
     * 验证文件
     */
    private static function validateFile($file, array $config): array
    {
        // 检查文件是否存在
        if (!$file) {
            return [
                'code' => 1,
                'msg' => '没有上传文件',
                'data' => null
            ];
        }

        // 检查文件大小
        if ($file->getSize() > $config['maxSize']) {
            $maxSizeMB = round($config['maxSize'] / 1024 / 1024, 2);
            return [
                'code' => 1,
                'msg' => "文件大小超出限制，最大允许 {$maxSizeMB}MB",
                'data' => null
            ];
        }

        // 检查文件扩展名
        $extension = strtolower(pathinfo($file->getInfo('name'), PATHINFO_EXTENSION));
        if (!in_array($extension, $config['allowExt'])) {
            $allowExtStr = implode(', ', $config['allowExt']);
            return [
                'code' => 1,
                'msg' => "不支持的文件格式，仅支持：{$allowExtStr}",
                'data' => null
            ];
        }

        return ['code' => 0];
    }

    /**
     * 获取文件信息
     */
    private static function getFileInfo($file, $info, array $config): array
    {
        // 构建文件URL路径（不包含web前缀，因为程序默认访问目录就是web目录）
        $relativePath = str_replace('\\', '/', $config['path'] . '/' . $info->getSaveName());
        $url = '/' . $relativePath;
        
        return [
            'original_name' => $file->getInfo('name'),
            'save_name' => $info->getSaveName(),
            'path' => $relativePath,
            'url' => $url,
            'size' => $file->getSize(),
            'mime_type' => $file->getMime(),
            'extension' => $info->getExtension(),
            'upload_time' => date('Y-m-d H:i:s'),
            'filename' => $info->getFilename()
        ];
    }

    /**
     * 生成缩略图
     */
    private static function generateThumbnail(string $imagePath, int $width = 120, int $height = 120): string
    {
        try {
            $webPath = dirname(ROOT_PATH) . DS . 'web' . DS;
            $fullPath = $webPath . $imagePath;
            
            if (!file_exists($fullPath)) {
                return '';
            }

            // 生成缩略图路径
            $pathInfo = pathinfo($imagePath);
            $thumbPath = $pathInfo['dirname'] . '/thumb_' . $pathInfo['basename'];
            $thumbFullPath = $webPath . str_replace('/', DS, $thumbPath);

            // 创建缩略图目录
            $thumbDir = dirname($thumbFullPath);
            if (!is_dir($thumbDir)) {
                mkdir($thumbDir, 0755, true);
            }

            // 使用ThinkPHP的Image类生成缩略图
            $image = \think\Image::open($fullPath);
            $image->thumb($width, $height, \think\Image::THUMB_CENTER)->save($thumbFullPath);

            return '/' . $thumbPath;

        } catch (\Exception $e) {
            // 缩略图生成失败不影响主要功能
            return '';
        }
    }

    /**
     * 删除文件
     */
    public static function deleteFile(string $path): bool
    {
        try {
            $webPath = dirname(ROOT_PATH) . DS . 'web' . DS;
            $fullPath = $webPath . str_replace('/', DS, $path);
            
            if (file_exists($fullPath)) {
                unlink($fullPath);
                
                // 同时删除缩略图（如果存在）
                $pathInfo = pathinfo($fullPath);
                $thumbPath = $pathInfo['dirname'] . DS . 'thumb_' . $pathInfo['basename'];
                if (file_exists($thumbPath)) {
                    unlink($thumbPath);
                }
                
                return true;
            }
            
            return false;
            
        } catch (\Exception $e) {
            return false;
        }
    }

    /**
     * 获取文件URL
     */
    public static function getFileUrl(string $path): string
    {
        try {
            return '/web/' . $path;
        } catch (\Exception $e) {
            return '';
        }
    }

    /**
     * 检查文件是否存在
     */
    public static function fileExists(string $path): bool
    {
        try {
            $webPath = dirname(ROOT_PATH) . DS . 'web' . DS;
            $fullPath = $webPath . str_replace('/', DS, $path);
            return file_exists($fullPath);
        } catch (\Exception $e) {
            return false;
        }
    }

    /**
     * 获取文件大小（人类可读格式）
     */
    public static function formatFileSize(int $size): string
    {
        $units = ['B', 'KB', 'MB', 'GB', 'TB'];
        
        for ($i = 0; $size >= 1024 && $i < 4; $i++) {
            $size /= 1024;
        }
        
        return round($size, 2) . ' ' . $units[$i];
    }

    /**
     * 删除素材
     */
    public static function deleteMaterial(string $path): array
    {
        try {
            $deleted = self::deleteFile($path);
            
            if ($deleted) {
                return [
                    'code' => 0,
                    'msg' => '删除成功'
                ];
            } else {
                // 文件可能已经不存在，但我们仍然返回成功
                return [
                    'code' => 2,
                    'msg' => '文件不存在，已视为删除成功'
                ];
            }
        } catch (\Exception $e) {
            return [
                'code' => 1,
                'msg' => '删除失败：' . $e->getMessage()
            ];
        }
    }
}